package algorithm;

import algorithm.AR.*;

public class AdaptiveRandomStrategy extends AlgorithmStrategy {
	private ValueFactory[] factories;
	private int candinum;
	public AdaptiveRandomStrategy(String filePath, String method,int tcNum,
			MParameter[] paraList) {
		super(filePath, method, tcNum,paraList);
		factories = new ValueFactory[paraList.length];
		candinum=5;//
		initFactory();
	}

	@Override
	protected void initFactory() {
		for (int i = 0; i < paraList.length; i++) {
			switch (paraList[i].getParaType()) {
			case STRING:
				factories[i] = new ARStringFactory(candinum);
				break;
			case INTEGER:
				factories[i] = new ARIntFactory(candinum);
				break;
			case DOUBLE:
				factories[i] = new ARDoubleFactory(candinum);
				break;
			case CHAR:
				factories[i] = new ARCharFactory(candinum);
				break;
			}

		}
		
	}
	public Object[][] getValues()
    {
		int count=0;//count the test case;
    	Object[][] returnvalues=new Object[paraList.length][tcNum];
    	Object[][] candivalues=new Object[paraList.length][candinum];
    	
    	if(paraList!=null)	
    	{  	
    		while(count<tcNum){
	    		//get candidates
	    		for (int i = 0; i < paraList.length; i++) {
	    			candivalues[i]=factories[i].getValue(paraList[i].getMin(),paraList[i].getMax());
	    		}
	    		//get each distance for candidates
	    		if(count==0) 
	    		{
	    			for(int m=0;m<paraList.length;m++)
	    			{
	    				returnvalues[m][0]=candivalues[m][0];
	    				factories[m].addTC(candivalues[m][0]);
	    			}
	    			
	    		}
	    		else 
	    			{
	    			double[][] distances=new double[candinum][count];
	    			//init;
	    			for(int i=0;i<candinum;i++)
	    				for(int j=0;j<count;j++)
	    					distances[i][j]=0.0;
	    			//get distance matrix;
	    			for(int f_num=0;f_num<paraList.length;f_num++){
			    		for(int c_num=0;c_num<candinum;c_num++)
			    		{
			    			double[] distance=new double[count];
			    			distance=factories[f_num].getDistance(candivalues[f_num][c_num]);
			    			for(int i=0;i<count;i++)
			    				distances[c_num][i]+=distance[i];
			    		}
		    			}
	    			//find the best candidate;
	    			//A candidate will be selected as the next test case 
	    			//if it has the longest distance to its nearest neighbour in exist test cases;
	    			int [] min_for_candi=new int[candinum];
	    			for(int i=0;i<candinum;i++){
	    				double temp_d=distances[i][0];
	    				int temp_i=0;
	    				for(int j=1;j<count;j++)
	    				{
	    					if(distances[i][j]<temp_d)
	    					{
	    						temp_d=distances[i][j];
	    						temp_i=j;
	    					}	    					
	    					
	    				}
	    				min_for_candi[i]=temp_i;
	    			}
	    			double temp_d2=distances[0][min_for_candi[0]];
	    			int candi_best=0;
	    			for(int i=0;i<candinum;i++)
	    			{
	    				if(distances[i][min_for_candi[i]]>temp_d2){
	    					temp_d2=distances[i][min_for_candi[i]];
	    					candi_best=i;
	    				}
	    			}
	    			
	    			for(int m=0;m<paraList.length;m++)
	    			{
	    				returnvalues[m][count]=candivalues[m][candi_best];
	    				factories[m].addTC(candivalues[m][candi_best]);
	    			}
	    			}
	    		count++;
    		}
    	}
    	return returnvalues;
    }
	

}
